複数AWSアカウントのユーザ管理を、ログイン用AWS環境に集約してみた
はじめに
AWSチームのすずきです。
IAM権限の分離や、請求情報の明確化を実現する手段として、AWSアカウントの分割を実施する事があります。
統合認証基盤と連携したSSOなどを利用しない場合、ユーザ管理の煩雑化が問題となる事がありましたが、 複数のAWSアカウントで構成された環境のIAMユーザ管理と、その権限管理を ログイン専用のAWS環境を用意し、効率化する機会がありました。
その内容について紹介させて頂きます。
概要図
基本方針
当該環境のAWS、IAMの利用方針は以下としました。
- 開発、本番環境では、IAMはRoleの利用を原則とします。
- IAMユーザはログイン環境のみに設置します。
- Roleに対応しないツールに限り、例外としてIAMユーザ(アクセスキー)の設置を認めます。
- 全てのIAMユーザは定期的な棚卸し対象とし、放置を回避します。
- 開発、本番環境のRole、2種類、参照専用(readonly)、変更可能(admin)を用意します。
- 変更可能(admin)なRoleは、管理者グループに所属するユーザに限定して提供します。
- Roleを利用(スイッチロール)する際、MFA必須、事前登録済みのIPアドレス以外での利用を禁止します。
- ログイン環境のIAMユーザの不正利用に備えます。
参考
ログイン環境から、開発本番環境の操作にはスイッチロールを利用します。その概要、利用方法は以下をご覧ください。
- 【新機能】IAMユーザーをManagement Consoleからクロスアカウントで色々なRoleにスイッチする事ができるようになりました。
- AWS CLIがAssumeRoleによる自動クレデンシャル取得とMFAに対応しました!
実装詳細
ログイン環境
IAMグループ
- IAMグループを利用し、ログイン環境のIAMユーザに付与する権限を管理します
- インラインポリシーを作成し、付与するIAM権限を設定します。
IAM更新用ポリシー
- 自身の認証情報(パスワード、MFA設定)に必要とするIAM権限を付与します。
- 「000000000000」はログイン環境のAWSアカウントIDに置き換えます。
- Policy-allow-iam-mfa-password
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "iam:ListUsers" ], "Resource": [ "arn:aws:iam::000000000000:user/" ], "Effect": "Allow" }, { "Action": [ "iam:ListVirtualMFADevices" ], "Resource": [ "arn:aws:iam::000000000000:mfa/" ], "Effect": "Allow" }, { "Action": [ "iam:EnableMFADevice", "iam:DeactivateMFADevice", "iam:ResyncMFADevice", "iam:ListMFADevices", "iam:ChangePassword" ], "Resource": [ "arn:aws:iam::000000000000:user/${aws:username}" ], "Effect": "Allow" }, { "Action": [ "iam:DeleteVirtualMFADevice", "iam:CreateVirtualMFADevice" ], "Resource": [ "arn:aws:iam::000000000000:mfa/${aws:username}" ], "Effect": "Allow" }, { "Action": [ "iam:GetAccountPasswordPolicy" ], "Resource": [ "arn:aws:iam::000000000000:*" ], "Effect": "Allow" } ] }
Role利用ポリシー
- 203.0.113.0/24、192.0.2.0/24、198.51.100.0/24 は、作業拠点、VPN環境などのグローバルIPに置き換えます。
- 開発環境(000000000001)、本番環境(000000000002)に設置したRoleの利用許可を、対象リソースを明示して与えます。
- PolicyGroupAdmin(管理者用)
{ "Version": "2012-10-17", "Statement": [ { "Condition": { "IpAddress": { "aws:SourceIp": [ "203.0.113.0/24", "192.0.2.0/24", "198.51.100.0/24" ] } }, "Action": [ "sts:AssumeRole" ], "Resource": [ "arn:aws:iam::000000000001:role/role-readonly*", "arn:aws:iam::000000000001:role/role-admin*", "arn:aws:iam::000000000002:role/role-readonly*", "arn:aws:iam::000000000002:role/role-admin*" ], "Effect": "Allow" } ] }
- PolicyGroupReadOnly(参照用)
{ "Version": "2012-10-17", "Statement": [ { "Condition": { "IpAddress": { "aws:SourceIp": [ "203.0.113.0/24", "192.0.2.0/24", "198.51.100.0/24" ] } }, "Action": [ "sts:AssumeRole" ], "Resource": [ "arn:aws:iam::000000000001:role/role-readonly*", "arn:aws:iam::000000000002:role/role-readonly*", ], "Effect": "Allow" } ] }
- スイッチロール(sts:AssumeRole)先を限定する事で、スイッチ先(開発、本番)でのユーザ管理を簡略化します。
- 複数のIAM Userがあるアカウントをスイッチ元として、クロスアカウント用IAM Roleを作る
開発、本番環境
共通
- 信頼関係「sts:AssumeRole」の許可先として、ログイン環境のAWSアカウントを指定します
- ログイン環境のIAMユーザの「sts:AssumeRole」は、「Resource:」を明示して設定されているものとします。
-
AWS操作をMFA必須とするため、条件として「aws:MultiFactorAuthPresent」を「true」とします。
管理者用
- 「Administrator」の管理ポリシーに相当する、IAMの全権限の許可を与えます
- 実環境では、開発、運用のフェーズや担当者の役割に応じた、より適切な管理ポリシー、ロールの利用をお勧めします。
参照専用
- 平時の確認作業を想定し、「ReadOnlyAccess」の管理ポリシーを付与しています。
- 管理ポリシー「ReadOnlyAccess」では不足するサービスの権限はインラインポリシーを追加します
- 今回、DynamoDBの不正参照や、スロットル回避の為、DynamoDBのScanを禁止(Deny)としています。
まとめ
AWSアカウントを複数用意した場合、アカウントの管理工数の増加が課題となる事がありましたが、 ログイン用のAWSアカウントを用意し、そのIAMを適切に設定する事で集約管理が実現できました。
Unixの「sudo」的にAWSアカウントをスイッチロールを実施する事で、 接続元IPの限定や、MFA利用の徹底、変更ログ(Cloudtrail)の作業者の明確化も可能になります。
ログイン環境で利用するIAMやSTSなどのAWSのサービスは課金対象外のサービスとなるため、 追加費用負担なく、多数のAWSアカウントを管理する環境として利用する事が可能です。
※CloudTrail、AWS Configなどを利用した場合、若干の費用は生じます。
複数のAWSアカウントの管理を効率化するサービスとしてAWS Organizationsが発表され、 2016年12月現在プレビュー募集が開始されていますが、 既存環境で、複数のAWSアカウントで構成されているIAM管理の見直しの機会がありましたら、 ログイン用のAWS環境を是非お試しください。
サンプル
- 今回紹介したサンプル環境を再現可能なCloudFormationテンプレートです。
ログイン環境用
- IAMグループ、IAMユーザを生成します
- 接続元IP(203.0.113.0/24、192.0.2.0/24、198.51.100.0/24) は置き換えます
- スイッチ先ロールのアカウント(000000000001、000000000002)も置き換えます
AWSTemplateFormatVersion: "2010-09-09" Description: "login account (IAM user, group)" Mappings: #IP制限の許可対象 IpAddress: base01: ip01: "203.0.113.0/24" ip02: "192.0.2.0/24" ip03: "198.51.100.0/24" Resources: #IAMユーザ(ログイン用) #パスワードはAWSマネジメントコンソールを利用して発行 IamUser01: Type: "AWS::IAM::User" Properties: UserName: "hogehoge" Groups: - Ref: GroupAdmin IamUser02: Type: "AWS::IAM::User" Properties: UserName: "fugafuga" Groups: - Ref: GroupReadonly #IAMグループ(Admin用) #000000000001、000000000002はスイッチ先のAWSアカウントに差替 GroupAdmin: Type: "AWS::IAM::Group" Properties: GroupName: "group-admin" Policies: - PolicyName: PolicyGroupAdmin PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "sts:AssumeRole" Resource: - "arn:aws:iam::000000000001:role/role-readonly*" - "arn:aws:iam::000000000001:role/role-admin*" - "arn:aws:iam::000000000002:role/role-readonly*" - "arn:aws:iam::000000000002:role/role-admin*" Condition: IpAddress: "aws:SourceIp": - "Fn::FindInMap": - IpAddress - base01 - ip01 - "Fn::FindInMap": - IpAddress - base01 - ip02 - "Fn::FindInMap": - IpAddress - base01 - ip03 #IAMグループ(ReadOnly用) GroupReadonly: Type: "AWS::IAM::Group" Properties: GroupName: "group-readonly" Policies: - PolicyName: PolicyGroupReadonly PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "sts:AssumeRole" Resource: - "arn:aws:iam::000000000001:role/role-readonly*" - "arn:aws:iam::000000000002:role/role-readonly*" Condition: IpAddress: "aws:SourceIp": - "Fn::FindInMap": - IpAddress - base01 - ip01 - "Fn::FindInMap": - IpAddress - base01 - ip02 - "Fn::FindInMap": - IpAddress - base01 - ip03 #IAMポリシー(共通:自身のパスワードとMFA変更を許可) PolicyAllowIamMfaPassword: Type: "AWS::IAM::Policy" Properties: PolicyName: "Policy-allow-iam-mfa-password" PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "iam:ListUsers" Resource: - "Fn::Join": - "" - - "arn:aws:iam::" - Ref: "AWS::AccountId" - ":user/" - Effect: Allow Action: - "iam:ListVirtualMFADevices" Resource: - "Fn::Join": - "" - - "arn:aws:iam::" - Ref: "AWS::AccountId" - ":mfa/" - Effect: Allow Action: - "iam:EnableMFADevice" - "iam:DeactivateMFADevice" - "iam:ResyncMFADevice" - "iam:ListMFADevices" - "iam:ChangePassword" Resource: - "Fn::Join": - "" - - "arn:aws:iam::" - Ref: "AWS::AccountId" - ":user/${aws:username}" - Effect: Allow Action: - "iam:DeleteVirtualMFADevice" - "iam:CreateVirtualMFADevice" Resource: - "Fn::Join": - "" - - "arn:aws:iam::" - Ref: "AWS::AccountId" - ":mfa/${aws:username}" - Effect: Allow Action: - "iam:GetAccountPasswordPolicy" Resource: - "Fn::Join": - "" - - "arn:aws:iam::" - Ref: "AWS::AccountId" - ":*" Groups: - Ref: GroupAdmin - Ref: GroupReadonly
開発、本番環境用
- 開発(000000000001)、本番(000000000002)のAWS環境に設置する、スイッチ先となるIAMロールを作成します。
- スイッチ元、ログイン環境のAWSアカウント(000000000000)を差し替えて利用します。 - Roleの種類を増やさない場合、各アカウント共通で利用可能です。
AWSTemplateFormatVersion: "2010-09-09" Description: "Create IAM Role (switch target) 201612" Parameters: OriginalAWSaccountID: Description: "Switch original AWSaccount ID" Type: String Default: "000000000000" Resources: RoleAdmin: Type: "AWS::IAM::Role" Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: "Fn::Join": - "" - - "arn:aws:iam::" - Ref: OriginalAWSaccountID - ":root" Action: "sts:AssumeRole" Condition: Bool: "aws:MultiFactorAuthPresent": true Policies: - PolicyName: RolepolicyAdmin PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - "*" Resource: - "*" RoleName: "role-admin" RoleReadonly: Type: "AWS::IAM::Role" Properties: ManagedPolicyArns: - "arn:aws:iam::aws:policy/ReadOnlyAccess" AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: AWS: "Fn::Join": - "" - - "arn:aws:iam::" - Ref: OriginalAWSaccountID - ":root" Action: "sts:AssumeRole" Condition: Bool: "aws:MultiFactorAuthPresent": true Policies: - PolicyName: RolepolicyDeny PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Action: - "dynamodb:Scan" Resource: - "*" RoleName: "role-readonly"